/**
 ******************************************************************************
 * @file           : log.h
 * @brief          : MicroLog - Lightweight logging library for embedded systems
 * @version        : 1.1.0
 * @date           : 2025-10-18
 ******************************************************************************
 * @attention
 *
 * MIT License
 * 
 * Copyright (c) 2025 MicroLog
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *
 ******************************************************************************
 */

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __LOG_H__
#define __LOG_H__

#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdarg.h>
#include "log_cfg.h"

/* Version information -------------------------------------------------------*/
#define LOG_VERSION_MAJOR       1       /*!< 主版本号: 重大变化时手动修改 */
#define LOG_VERSION_MINOR       1       /*!< 次版本号: 新增或修改时手动修改 */
#define LOG_VERSION_PATCH       0       /*!< 修订版本号: 问题修复时手动修改 */

/* Exported constants --------------------------------------------------------*/
/**
 * @brief 日志级别定义（数值越小优先级越高）
 */
#define LOG_LEVEL_OFF      0    /*!< 关闭所有日志 */
#define LOG_LEVEL_FATAL    1    /*!< 致命错误（系统崩溃）*/
#define LOG_LEVEL_ERROR    2    /*!< 错误（功能失败）*/
#define LOG_LEVEL_WARN     3    /*!< 警告（潜在问题）*/
#define LOG_LEVEL_INFO     4    /*!< 信息（关键流程）*/
#define LOG_LEVEL_DEBUG    5    /*!< 调试（详细信息）*/
#define LOG_LEVEL_TRACE    6    /*!< 追踪（最详细）*/
#define LOG_LEVEL_ALL      7    /*!< 显示所有日志 */

/**
 * @brief 预定义模块标签
 */
#define TAG_SYSTEM      "SYS"       /*!< 系统模块 */
#define TAG_PARAM       "PARAM"     /*!< 参数管理 */
#define TAG_EEPROM      "EEPROM"    /*!< EEPROM */
#define TAG_MENU        "MENU"      /*!< 菜单系统 */
#define TAG_FLOW        "FLOW"      /*!< 流量测量 */
#define TAG_TEMP        "TEMP"      /*!< 温度测量 */
#define TAG_SWITCH      "SWITCH"    /*!< 开关输出 */
#define TAG_ADC         "ADC"       /*!< ADC */
#define TAG_DAC         "DAC"       /*!< DAC */
#define TAG_LCD         "LCD"       /*!< 液晶屏 */
#define TAG_KEY         "KEY"       /*!< 按键 */
#define TAG_APP         "APP"       /*!< 应用层 */

/* Exported types ------------------------------------------------------------*/
/**
 * @brief 日志格式索引枚举
 */
typedef enum
{
    LOG_FMT_TIME    = 1 << 0,           /*!< 时间戳 */
    LOG_FMT_LVL     = 1 << 1,           /*!< 日志级别 */
    LOG_FMT_TAG     = 1 << 2,           /*!< 模块标签 */
    LOG_FMT_TASK    = 1 << 3,           /*!< 任务信息 */
    LOG_FMT_FUNC    = 1 << 4,           /*!< 函数名 */
    LOG_FMT_LINE    = 1 << 5,           /*!< 行号 */
} log_fmt_index_e;

/* 格式组合宏 */
#define LOG_FMT_ALL     (LOG_FMT_TIME | LOG_FMT_LVL | LOG_FMT_TAG | LOG_FMT_TASK | LOG_FMT_FUNC | LOG_FMT_LINE)   /*!< 所有字段 */
#define LOG_FMT_SIMPLE  (LOG_FMT_LVL | LOG_FMT_TAG)                     /*!< 简洁模式（无时间戳）*/
#define LOG_FMT_MINIMAL (LOG_FMT_LVL)                                   /*!< 最简模式（只有级别）*/

/**
 * @brief 日志输出函数类型定义
 * 
 * @param[in]   log: 日志内容指针
 * @param[in]   size: 日志内容长度
 * 
 * @note        用于log_set_output()，可将日志重定向到自定义输出（文件、网络等）
 */
typedef void (*log_output_fn)(const char *log, size_t size);

/* Exported macro ------------------------------------------------------------*/
/**
 * @brief 辅助宏：固定参数传递
 */
#if LOG_ENABLE_FUNC
    #define LOG_OUTPUT_FUNC         __func__
#else
    #define LOG_OUTPUT_FUNC         NULL
#endif

#if LOG_ENABLE_LINE
    #define LOG_OUTPUT_LINE         __LINE__
#else
    #define LOG_OUTPUT_LINE         0
#endif

/**
 * @brief 日志输出宏（带标签，需显式指定标签）
 * @note  适用于需要在同一文件中使用不同标签的场景
 */
#if LOG_LEVEL_FATAL <= LOG_COMPILE_LEVEL
    #define LOG_F(tag, fmt, ...) log_output(LOG_LEVEL_FATAL, tag, LOG_OUTPUT_FUNC, LOG_OUTPUT_LINE, fmt, ##__VA_ARGS__)
#else
    #define LOG_F(tag, fmt, ...) ((void)0)
#endif

#if LOG_LEVEL_ERROR <= LOG_COMPILE_LEVEL
    #define LOG_E(tag, fmt, ...) log_output(LOG_LEVEL_ERROR, tag, LOG_OUTPUT_FUNC, LOG_OUTPUT_LINE, fmt, ##__VA_ARGS__)
#else
    #define LOG_E(tag, fmt, ...) ((void)0)
#endif

#if LOG_LEVEL_WARN <= LOG_COMPILE_LEVEL
    #define LOG_W(tag, fmt, ...) log_output(LOG_LEVEL_WARN, tag, LOG_OUTPUT_FUNC, LOG_OUTPUT_LINE, fmt, ##__VA_ARGS__)
#else
    #define LOG_W(tag, fmt, ...) ((void)0)
#endif

#if LOG_LEVEL_INFO <= LOG_COMPILE_LEVEL
    #define LOG_I(tag, fmt, ...) log_output(LOG_LEVEL_INFO, tag, LOG_OUTPUT_FUNC, LOG_OUTPUT_LINE, fmt, ##__VA_ARGS__)
#else
    #define LOG_I(tag, fmt, ...) ((void)0)
#endif

#if LOG_LEVEL_DEBUG <= LOG_COMPILE_LEVEL
    #define LOG_D(tag, fmt, ...) log_output(LOG_LEVEL_DEBUG, tag, LOG_OUTPUT_FUNC, LOG_OUTPUT_LINE, fmt, ##__VA_ARGS__)
#else
    #define LOG_D(tag, fmt, ...) ((void)0)
#endif

#if LOG_LEVEL_TRACE <= LOG_COMPILE_LEVEL
    #define LOG_T(tag, fmt, ...) log_output(LOG_LEVEL_TRACE, tag, LOG_OUTPUT_FUNC, LOG_OUTPUT_LINE, fmt, ##__VA_ARGS__)
#else
    #define LOG_T(tag, fmt, ...) ((void)0)
#endif

/**
 * @brief 文件级标签宏
 * @note  在源文件开头定义 LOG_TAG，然后使用小写的 log_i/log_e 等简化宏
 *        这是最简洁的使用方式，每个文件可以定义自己的标签
 */
#if !defined(LOG_TAG)
    #define LOG_TAG     "NO_TAG"        /*!< 默认标签（未定义时的警示） */
#endif

#define log_f(fmt, ...)     LOG_F(LOG_TAG, fmt, ##__VA_ARGS__)
#define log_e(fmt, ...)     LOG_E(LOG_TAG, fmt, ##__VA_ARGS__)
#define log_w(fmt, ...)     LOG_W(LOG_TAG, fmt, ##__VA_ARGS__)
#define log_i(fmt, ...)     LOG_I(LOG_TAG, fmt, ##__VA_ARGS__)
#define log_d(fmt, ...)     LOG_D(LOG_TAG, fmt, ##__VA_ARGS__)
#define log_t(fmt, ...)     LOG_T(LOG_TAG, fmt, ##__VA_ARGS__)

#define log_hex_f(data, len)    LOG_HEX_F(LOG_TAG, data, len)
#define log_hex_e(data, len)    LOG_HEX_E(LOG_TAG, data, len)
#define log_hex_w(data, len)    LOG_HEX_W(LOG_TAG, data, len)
#define log_hex_i(data, len)    LOG_HEX_I(LOG_TAG, data, len)
#define log_hex_d(data, len)    LOG_HEX_D(LOG_TAG, data, len)
#define log_hex_t(data, len)    LOG_HEX_T(LOG_TAG, data, len)

/**
 * @brief HEX 数据转储宏（带标签，需显式指定标签）
 * @note  用于输出二进制数据的十六进制表示，每行16字节
 */
#if LOG_LEVEL_FATAL <= LOG_COMPILE_LEVEL
    #define LOG_HEX_F(tag, data, len) log_hex_dump(LOG_LEVEL_FATAL, tag, data, len)
#else
    #define LOG_HEX_F(tag, data, len) ((void)0)
#endif

#if LOG_LEVEL_ERROR <= LOG_COMPILE_LEVEL
    #define LOG_HEX_E(tag, data, len) log_hex_dump(LOG_LEVEL_ERROR, tag, data, len)
#else
    #define LOG_HEX_E(tag, data, len) ((void)0)
#endif

#if LOG_LEVEL_WARN <= LOG_COMPILE_LEVEL
    #define LOG_HEX_W(tag, data, len) log_hex_dump(LOG_LEVEL_WARN, tag, data, len)
#else
    #define LOG_HEX_W(tag, data, len) ((void)0)
#endif

#if LOG_LEVEL_INFO <= LOG_COMPILE_LEVEL
    #define LOG_HEX_I(tag, data, len) log_hex_dump(LOG_LEVEL_INFO, tag, data, len)
#else
    #define LOG_HEX_I(tag, data, len) ((void)0)
#endif

#if LOG_LEVEL_DEBUG <= LOG_COMPILE_LEVEL
    #define LOG_HEX_D(tag, data, len) log_hex_dump(LOG_LEVEL_DEBUG, tag, data, len)
#else
    #define LOG_HEX_D(tag, data, len) ((void)0)
#endif

#if LOG_LEVEL_TRACE <= LOG_COMPILE_LEVEL
    #define LOG_HEX_T(tag, data, len) log_hex_dump(LOG_LEVEL_TRACE, tag, data, len)
#else
    #define LOG_HEX_T(tag, data, len) ((void)0)
#endif

/**
 * @brief 断言宏（仅在 DEBUG 模式生效）
 * @note  断言失败时输出错误信息并进入死循环
 *        Release 模式下编译为空操作，不占用 ROM
 */
#if LOG_ENABLE_ASSERT
    #define LOG_ASSERT(expr) \
        do { \
            if (!(expr)) { \
                log_raw("[ASSERT] %s:%d - %s" LOG_NEWLINE, __FILE__, __LINE__, #expr); \
                while(1); \
            } \
        } while(0)
#else
    #define LOG_ASSERT(expr) ((void)0)
#endif

/**
 * @brief 原始输出宏（不带格式）
 */
#define LOG_RAW(fmt, ...) log_raw(fmt, ##__VA_ARGS__)

/* Exported functions --------------------------------------------------------*/
/* 初始化与控制 */
void log_init(void);                                                            /* 初始化日志系统 */
void log_deinit(void);                                                          /* 反初始化日志系统 */

/* 全局级别控制 */
void log_set_global_level(uint8_t level);                                       /* 设置全局日志级别 */
uint8_t log_get_global_level(void);                                             /* 获取全局日志级别 */

/* 模块标签级别过滤 */
void log_set_tag_level(const char *tag, uint8_t level);                         /* 设置模块标签级别 */
uint8_t log_get_tag_level(const char *tag);                                     /* 获取模块标签级别 */
void log_clear_tag_level(const char *tag);                                      /* 清除模块标签级别 */
void log_clear_all_tag_levels(void);                                            /* 清除所有模块标签级别 */

/* 格式配置 */
void log_set_fmt(uint8_t level, size_t set);                                    /* 设置指定级别的输出格式 */
size_t log_get_fmt(uint8_t level);                                              /* 获取指定级别的格式 */

/* 输出控制 */
void log_set_output(log_output_fn func);                                        /* 设置自定义输出函数 */
void log_set_output_enabled(bool enabled);                                      /* 设置输出使能 */
bool log_get_output_enabled(void);                                              /* 获取输出使能状态 */

/* 日志输出函数 */
void log_raw(const char *fmt, ...);                                             /* 原始输出 */
void log_output(uint8_t level, const char *tag, const char *func, int line, const char *fmt, ...);  /* 格式化输出 */
void log_hex_dump(uint8_t level, const char *tag, const void *data, uint16_t len);  /* HEX输出 */

#ifdef __cplusplus
}
#endif

#endif /* __LOG_H__ */
